#include<bits/stdc++.h>
#define ll long long
#define lson k<<1
#define rson k<<1|1
using namespace std;
const int N=100005;
int n,m,P;
ll a[N];
struct node{
	int l,r;
	ll sum,add,mul;
	#define l(k) tree[k].l
	#define r(k) tree[k].r
	#define sum(k) tree[k].sum
	#define add(k) tree[k].add
	#define mul(k) tree[k].mul
}tree[N<<2];
inline void build(int k,int x,int y){
	l(k)=x;r(k)=y;mul(k)=1;
	if(x==y){
		sum(k)=a[x]%P;
		return;
	}
	int mid=(x+y)>>1;
	build(lson,x,mid);build(rson,mid+1,y);
	sum(k)=(sum(lson)+sum(rson))%P;
}
inline void clear(int k){
	if(mul(k)!=1){
		(mul(lson)*=mul(k))%=P;
		(mul(rson)*=mul(k))%=P;
		(add(lson)*=mul(k))%=P;
		(add(rson)*=mul(k))%=P;
		(sum(lson)*=mul(k))%=P;
		(sum(rson)*=mul(k))%=P;
		mul(k)=1;
	}
	if(add(k)){
		(add(lson)+=add(k))%=P;
		(add(rson)+=add(k))%=P;
		(sum(lson)+=add(k)*(r(lson)-l(lson)+1))%=P;
		(sum(rson)+=add(k)*(r(rson)-l(rson)+1))%=P;
		add(k)=0;
	}
}
inline void Add(int k,int x,int y,int z){
	if(x<=l(k)&&y>=r(k)){
		(sum(k)+=(r(k)-l(k)+1)*z)%=P;
		(add(k)+=z)%=P;
		return;
	}
	clear(k);
	int mid=(l(k)+r(k))>>1;
	if(x<=mid)Add(lson,x,y,z);
	if(y>mid)Add(rson,x,y,z);
	sum(k)=(sum(lson)+sum(rson))%P;
}
inline void Mul(int k,int x,int y,int z){
	if(x<=l(k)&&y>=r(k)){
		(mul(k)*=z)%=P;
		(add(k)*=z)%=P;
		(sum(k)*=z)%=P;
		return;
	}
	clear(k);
	int mid=(l(k)+r(k))>>1;
	if(x<=mid)Mul(lson,x,y,z);
	if(y>mid)Mul(rson,x,y,z);
	sum(k)=(sum(lson)+sum(rson))%P;
}
inline ll Ask(int k,int x,int y){
	if(x<=l(k)&&y>=r(k))return sum(k)%P;
	clear(k);
	ll ret=0;
	int mid=(l(k)+r(k))>>1;
	if(x<=mid)ret+=Ask(lson,x,y);
	if(y>mid)ret+=Ask(rson,x,y);
	return ret%P;
}
int main(){
	scanf("%d%d%d",&n,&m,&P);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
	build(1,1,n);
	for(int i=1,pos,x,y,z;i<=m;++i){
		scanf("%d%d%d",&pos,&x,&y);
		if(pos==1){
			scanf("%d",&z);
			Mul(1,x,y,z);
		}else if(pos==2){
			scanf("%d",&z);
			Add(1,x,y,z);
		}else printf("%lld\n",Ask(1,x,y));
	}
	return 0;
}